import gradio as gr
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from typing import Tuple, Dict, List
import json
from pathlib import Path

def load_data(file) -> Tuple[pd.DataFrame, str]:
    """
    加载CSV或Excel文件数据。
    
    Args:
        file: 上传的文件路径
        
    Returns:
        数据框和消息
    """
    try:
        file_path = Path(file.name)
        if file_path.suffix.lower() == '.csv':
            df = pd.read_csv(file)
        elif file_path.suffix.lower() in ['.xlsx', '.xls']:
            df = pd.read_excel(file)
        else:
            return None, "错误：不支持的文件格式。请上传CSV或Excel文件。"
        
        # 验证数据格式
        required_columns = ['time_point', 'sensor_1']
        if not all(col in df.columns for col in required_columns):
            return None, "错误：数据格式不正确。请确保包含必要的列（time_point和sensor_x）。"
            
        return df, "数据加载成功！"
    except Exception as e:
        return None, f"错误：{str(e)}"

def plot_sensor_data(df: pd.DataFrame) -> go.Figure:
    """
    绘制传感器数据时间序列图。
    """
    if df is None:
        return None
        
    # 找出所有传感器列
    sensor_cols = [col for col in df.columns if col.startswith('sensor_')]
    
    # 创建图表
    fig = go.Figure()
    
    for col in sensor_cols:
        fig.add_trace(go.Scatter(
            x=df['time_point'],
            y=df[col],
            name=col,
            mode='lines'
        ))
    
    fig.update_layout(
        title="传感器响应曲线",
        xaxis_title="时间点",
        yaxis_title="传感器响应值",
        template="plotly_white"
    )
    
    return fig

def extract_features(df: pd.DataFrame) -> Dict:
    """
    提取数据特征。
    """
    if df is None:
        return {}
        
    features = {}
    sensor_cols = [col for col in df.columns if col.startswith('sensor_')]
    
    for col in sensor_cols:
        features[col] = {
            "均值": float(df[col].mean()),
            "标准差": float(df[col].std()),
            "最大值": float(df[col].max()),
            "最小值": float(df[col].min()),
            "峰峰值": float(df[col].max() - df[col].min()),
            "均方根": float(np.sqrt(np.mean(df[col]**2))),
            "偏度": float(df[col].skew()),
            "峰度": float(df[col].kurtosis())
        }
    
    return features

def analyze_data(file) -> Tuple[Dict, go.Figure, str]:
    """
    分析上传的数据文件。
    """
    # 加载数据
    df, message = load_data(file)
    if df is None:
        return {}, None, message
    
    # 绘制图表
    plot = plot_sensor_data(df)
    
    # 提取特征
    features = extract_features(df)
    
    return features, plot, message

# 创建Gradio界面
with gr.Blocks(title="电子鼻数据分析", theme=gr.themes.Soft()) as iface:
    gr.Markdown("""
    # 电子鼻数据分析工具
    
    上传CSV或Excel格式的传感器数据文件进行分析。文件应包含以下列：
    - time_point：时间点
    - sensor_1, sensor_2, ...：传感器数据
    - 可选：temperature, humidity等元数据
    """)
    
    with gr.Row():
        file_input = gr.File(
            label="上传数据文件",
            file_types=[".csv", ".xlsx", ".xls"]
        )
    
    with gr.Row():
        analyze_btn = gr.Button("分析数据", variant="primary")
    
    with gr.Row():
        status_output = gr.Textbox(label="状态信息")
    
    with gr.Tabs():
        with gr.TabItem("数据可视化"):
            plot_output = gr.Plot(label="传感器响应曲线")
        
        with gr.TabItem("特征分析"):
            features_output = gr.JSON(label="特征统计")
    
    analyze_btn.click(
        fn=analyze_data,
        inputs=[file_input],
        outputs=[features_output, plot_output, status_output]
    )

if __name__ == "__main__":
    iface.launch() 